package websocket

import (
	"encoding/json"
	"errors"
	"sync"
)

// Room WebSocket 房间（线程安全）
type Room struct {
	ID           string                    // 房间ID
	connections  map[string]*Connection    // 连接ID -> Connection 映射
	members      map[string]interface{}    // 成员信息（连接ID -> 成员数据）
	mu           sync.RWMutex              // 读写锁
	onJoin       func(*Room, string)       // 成员加入回调
	onLeave      func(*Room, string)       // 成员离开回调
	onMessage    func(*Room, string, []byte) error // 房间消息处理回调
}

// NewRoom 创建新房间
func NewRoom(roomID string) *Room {
	return &Room{
		ID:          roomID,
		connections: make(map[string]*Connection),
		members:     make(map[string]interface{}),
	}
}

// Join 加入房间
func (r *Room) Join(connectionID string, conn *Connection, memberData interface{}) error {
	if conn == nil {
		return errors.New("connection is nil")
	}

	r.mu.Lock()
	defer r.mu.Unlock()

	// 如果已存在，先离开
	if _, exists := r.connections[connectionID]; exists {
		r.leaveUnsafe(connectionID)
	}

	r.connections[connectionID] = conn
	if memberData != nil {
		r.members[connectionID] = memberData
	}

	// 触发加入回调
	if r.onJoin != nil {
		go r.onJoin(r, connectionID)
	}

	return nil
}

// Leave 离开房间
func (r *Room) Leave(connectionID string) {
	r.mu.Lock()
	defer r.mu.Unlock()
	r.leaveUnsafe(connectionID)
}

// leaveUnsafe 离开房间（不加锁，必须在已加锁的情况下调用）
func (r *Room) leaveUnsafe(connectionID string) {
	if _, exists := r.connections[connectionID]; !exists {
		return
	}

	delete(r.connections, connectionID)
	delete(r.members, connectionID)

	// 触发离开回调
	if r.onLeave != nil {
		go r.onLeave(r, connectionID)
	}
}

// Broadcast 广播消息到房间内所有连接
func (r *Room) Broadcast(message []byte) error {
	r.mu.RLock()
	defer r.mu.RUnlock()

	if len(r.connections) == 0 {
		return nil
	}

	var errs []error
	for id, conn := range r.connections {
		if err := conn.Send(message); err != nil {
			// 发送失败，可能是连接已断开，移除连接
			errs = append(errs, err)
			// 异步清理失效连接
			go func(connID string) {
				r.Leave(connID)
			}(id)
		}
	}

	if len(errs) > 0 {
		return errors.New("some connections failed to send message")
	}

	return nil
}

// BroadcastJSON 广播 JSON 消息
func (r *Room) BroadcastJSON(v interface{}) error {
	data, err := json.Marshal(v)
	if err != nil {
		return err
	}
	return r.Broadcast(data)
}

// BroadcastMessage 广播结构化消息
func (r *Room) BroadcastMessage(msgType string, payload interface{}) error {
	msg := Message{
		Type:    msgType,
		Payload: payload,
	}
	return r.BroadcastJSON(msg)
}

// SendToMember 发送消息给房间内特定成员
func (r *Room) SendToMember(connectionID string, message []byte) error {
	r.mu.RLock()
	defer r.mu.RUnlock()

	conn, exists := r.connections[connectionID]
	if !exists {
		return errors.New("member not found in room")
	}

	return conn.Send(message)
}

// SendJSONToMember 发送 JSON 消息给房间内特定成员
func (r *Room) SendJSONToMember(connectionID string, v interface{}) error {
	data, err := json.Marshal(v)
	if err != nil {
		return err
	}
	return r.SendToMember(connectionID, data)
}

// SendMessageToMember 发送结构化消息给房间内特定成员
func (r *Room) SendMessageToMember(connectionID string, msgType string, payload interface{}) error {
	msg := Message{
		Type:    msgType,
		Payload: payload,
	}
	return r.SendJSONToMember(connectionID, msg)
}

// HandleMessage 处理房间消息（触发回调）
func (r *Room) HandleMessage(connectionID string, message []byte) error {
	if r.onMessage != nil {
		return r.onMessage(r, connectionID, message)
	}
	return nil
}

// GetMemberCount 获取房间成员数
func (r *Room) GetMemberCount() int {
	r.mu.RLock()
	defer r.mu.RUnlock()
	return len(r.connections)
}

// GetMembers 获取所有成员ID
func (r *Room) GetMembers() []string {
	r.mu.RLock()
	defer r.mu.RUnlock()
	
	members := make([]string, 0, len(r.connections))
	for id := range r.connections {
		members = append(members, id)
	}
	return members
}

// GetMemberData 获取成员数据
func (r *Room) GetMemberData(connectionID string) (interface{}, bool) {
	r.mu.RLock()
	defer r.mu.RUnlock()
	data, exists := r.members[connectionID]
	return data, exists
}

// GetAllMembersData 获取所有成员数据
func (r *Room) GetAllMembersData() map[string]interface{} {
	r.mu.RLock()
	defer r.mu.RUnlock()
	
	result := make(map[string]interface{})
	for id, data := range r.members {
		result[id] = data
	}
	return result
}

// IsMember 检查是否在房间内
func (r *Room) IsMember(connectionID string) bool {
	r.mu.RLock()
	defer r.mu.RUnlock()
	_, exists := r.connections[connectionID]
	return exists
}

// SetOnJoin 设置加入回调
func (r *Room) SetOnJoin(callback func(*Room, string)) {
	r.mu.Lock()
	defer r.mu.Unlock()
	r.onJoin = callback
}

// SetOnLeave 设置离开回调
func (r *Room) SetOnLeave(callback func(*Room, string)) {
	r.mu.Lock()
	defer r.mu.Unlock()
	r.onLeave = callback
}

// SetOnMessage 设置消息处理回调
func (r *Room) SetOnMessage(callback func(*Room, string, []byte) error) {
	r.mu.Lock()
	defer r.mu.Unlock()
	r.onMessage = callback
}

// Close 关闭房间（移除所有连接）
func (r *Room) Close() {
	r.mu.Lock()
	defer r.mu.Unlock()

	// 清理所有连接（不触发离开回调）
	for id := range r.connections {
		delete(r.connections, id)
		delete(r.members, id)
	}
}

